{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    id trade   order    price  lots\n",
      "0    1   buy   limit  1299.98    10\n",
      "1    2  sell   limit  1300.03    10\n",
      "2    3   buy  market      NaN     5\n",
      "3    4  sell  market      NaN    10\n",
      "4    5   buy  market      NaN     2\n",
      "5    6   buy   limit  1299.99     2\n",
      "6    7   buy  market      NaN   100\n",
      "7    8  sell   limit  1300.00    10\n",
      "8    9  sell   limit  1300.01    30\n",
      "9   10  sell  market      NaN    30\n",
      "10  11   buy  market      NaN    20\n",
      "11  12   buy   limit  1299.98    20\n",
      "12  13   buy  market      NaN    50\n",
      "13  14  sell   limit  1299.99    20\n",
      "14  15  sell  market      NaN    60\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   20\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00  100\n",
      "     price  num\n",
      "0  1299.99    2\n",
      "1  1299.98   10\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n"
     ]
    }
   ],
   "source": [
    "# 读取交易记录\n",
    "df_trade = pd.read_excel('lab1.xlsx')\n",
    "df_sell = pd.read_csv('lab1_sell_book.csv')\n",
    "df_buy = pd.read_csv('lab1_buy_book.csv')\n",
    "print(df_trade)\n",
    "print(df_sell)\n",
    "print(df_buy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 判断是否能够继续进行交易\n",
    "def transaction(typ, lots):\n",
    "    if lots == 0:\n",
    "        return False  # 委托的手数都交易完了，终止\n",
    "    if typ == 'buy':\n",
    "        return any(df_sell.num)  # num全为0，也要终止\n",
    "    else:\n",
    "        return any(df_buy.num)\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------第1次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   20\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00  100\n",
      "     price  num\n",
      "0  1299.99    2\n",
      "1  1299.98   20\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n",
      "--------第2次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00  100\n",
      "     price  num\n",
      "0  1299.99    2\n",
      "1  1299.98   20\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n",
      "--------第3次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00   95\n",
      "     price  num\n",
      "0  1299.99    2\n",
      "1  1299.98   20\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n",
      "--------第4次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00   95\n",
      "     price  num\n",
      "1  1299.98   12\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n",
      "--------第5次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00   93\n",
      "     price  num\n",
      "1  1299.98   12\n",
      "2  1299.97   50\n",
      "3  1299.96  100\n",
      "4  1299.95    2\n",
      "--------第6次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02   10\n",
      "4  1300.01    5\n",
      "5  1300.00   93\n",
      "     price    num\n",
      "4  1299.99    2.0\n",
      "0  1299.98   12.0\n",
      "1  1299.97   50.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第7次交易--------\n",
      "     price  num\n",
      "0  1300.05  100\n",
      "1  1300.04   30\n",
      "2  1300.03   30\n",
      "3  1300.02    8\n",
      "     price    num\n",
      "4  1299.99    2.0\n",
      "0  1299.98   12.0\n",
      "1  1299.97   50.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第8次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03   30.0\n",
      "3  1300.02    8.0\n",
      "4  1300.00   10.0\n",
      "     price    num\n",
      "4  1299.99    2.0\n",
      "0  1299.98   12.0\n",
      "1  1299.97   50.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第9次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03   30.0\n",
      "3  1300.02    8.0\n",
      "5  1300.01   30.0\n",
      "4  1300.00   10.0\n",
      "     price    num\n",
      "4  1299.99    2.0\n",
      "0  1299.98   12.0\n",
      "1  1299.97   50.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第10次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03   30.0\n",
      "3  1300.02    8.0\n",
      "5  1300.01   30.0\n",
      "4  1300.00   10.0\n",
      "     price    num\n",
      "1  1299.97   34.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第11次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03   30.0\n",
      "3  1300.02    8.0\n",
      "5  1300.01   20.0\n",
      "     price    num\n",
      "1  1299.97   34.0\n",
      "2  1299.96  100.0\n",
      "3  1299.95    2.0\n",
      "--------第12次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03   30.0\n",
      "3  1300.02    8.0\n",
      "5  1300.01   20.0\n",
      "     price    num\n",
      "3  1299.98   20.0\n",
      "0  1299.97   34.0\n",
      "1  1299.96  100.0\n",
      "2  1299.95    2.0\n",
      "--------第13次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03    8.0\n",
      "     price    num\n",
      "3  1299.98   20.0\n",
      "0  1299.97   34.0\n",
      "1  1299.96  100.0\n",
      "2  1299.95    2.0\n",
      "--------第14次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03    8.0\n",
      "3  1299.99   20.0\n",
      "     price    num\n",
      "3  1299.98   20.0\n",
      "0  1299.97   34.0\n",
      "1  1299.96  100.0\n",
      "2  1299.95    2.0\n",
      "--------第15次交易--------\n",
      "     price    num\n",
      "0  1300.05  100.0\n",
      "1  1300.04   30.0\n",
      "2  1300.03    8.0\n",
      "3  1299.99   20.0\n",
      "     price   num\n",
      "1  1299.96  94.0\n",
      "2  1299.95   2.0\n"
     ]
    }
   ],
   "source": [
    "# 迭代每一步交易，每一行为一步\n",
    "for idx, row in df_trade.iterrows():\n",
    "\n",
    "    lots = row.lots  # 需要交易的手数\n",
    "\n",
    "    # 首先确定交易类型，市价还是限价\n",
    "    if row.order == 'market':  # 市价交易，每一段都要寻找最优\n",
    "        if row.trade == 'buy':\n",
    "            i = -1\n",
    "            while transaction('buy', lots):\n",
    "                if lots <= df_sell.iloc[i, -1]:  # 如果当前行可以交易完\n",
    "                    df_sell.iloc[i, -1] -= lots\n",
    "                    lots = 0\n",
    "                else:\n",
    "                    lots -= df_sell.iloc[i, -1]\n",
    "                    df_sell.iloc[i, -1] = 0\n",
    "                    i -= 1  # 移动到上一行继续交易\n",
    "        else:\n",
    "            i = 0\n",
    "            while transaction('sell', lots):\n",
    "                if lots <= df_buy.iloc[i, -1]:\n",
    "                    df_buy.iloc[i, -1] -= lots\n",
    "                    lots = 0\n",
    "                else:\n",
    "                    lots -= df_buy.iloc[i, -1]\n",
    "                    df_buy.iloc[i, -1] = 0\n",
    "                    i += 1  # 移动到下一行继续交易\n",
    "    else:  # 限价交易。如果不能满足需求，挂到order book上\n",
    "        if row.trade == 'buy':\n",
    "            i = -1  # 从市价开始买入\n",
    "            # 比market order多了一个限价要求\n",
    "            while transaction('buy', lots) and row.price >= df_sell.iloc[i, 0]:\n",
    "                if lots <= df_sell.iloc[i, -1]:  # 如果当前行可以交易完\n",
    "                    df_sell.iloc[i, -1] -= lots\n",
    "                    lots = 0\n",
    "                else:\n",
    "                    lots -= df_sell.iloc[i, -1]\n",
    "                    df_sell.iloc[i, -1] = 0\n",
    "                    i -= 1  # 移动到上一行继续交易\n",
    "            if lots:  # 没交易完的order挂上去\n",
    "                row_idx = df_buy[df_buy.price == row.price].index\n",
    "                # 如果存在条目，则直接更新\n",
    "                if row_idx.size:\n",
    "                    df_buy.iloc[row_idx, 1] += lots\n",
    "                # 指定的价格不存在，则添加后降序排序\n",
    "                else:\n",
    "                    df_buy = df_buy.append(\n",
    "                        {'price': row.price, 'num': lots}, ignore_index=True)\n",
    "                    df_buy = df_buy.sort_values(by=['price'], ascending=False)\n",
    "        else:\n",
    "            i = 0\n",
    "            while transaction('sell', lots) and row.price <= df_buy.iloc[i, 0]:\n",
    "                if lots <= df_buy.iloc[i, -1]:\n",
    "                    df_buy.iloc[i, -1] -= lots\n",
    "                    lots = 0\n",
    "                else:\n",
    "                    lots -= df_buy.iloc[i, -1]\n",
    "                    df_buy.iloc[i, -1] = 0\n",
    "                    i += 1  # 移动到下一行继续交易\n",
    "            if lots:\n",
    "                row_idx = df_sell[df_sell.price == row.price].index\n",
    "                if row_idx.size:\n",
    "                    df_sell.iloc[row_idx, 1] += lots\n",
    "                else:\n",
    "                    df_sell = df_sell.append(\n",
    "                        {'price': row.price, 'num': lots}, ignore_index=True)\n",
    "                    df_sell = df_sell.sort_values(\n",
    "                        by=['price'], ascending=False)\n",
    "\n",
    "    # 最后删掉已经交易完的\n",
    "    df_buy.drop(df_buy[df_buy.num == 0].index, axis=0, inplace=True)\n",
    "    df_sell.drop(df_sell[df_sell.num == 0].index, axis=0, inplace=True)\n",
    "\n",
    "    # 打印更新后的order book\n",
    "    print(f'--------第{idx+1}次交易--------')\n",
    "    print(df_sell)\n",
    "    print(df_buy)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
